/*

 */
#include <system.h>
#include <v93.h>
#include <sup.h>
#include "libm.h"
#include "intlib.h"

#define SUP_XMAX    32			/* HuC6270-BG 横幅 */
#define SUP_YMAX    32			/* HuC6270-BG 縦幅 */
#define SAT_TOP     0x2000		/* SAT先頭アドレス */
#define SAT_SIZE    0x2 * 4		/* SATに１個に必要なサイズ */
#define PATTERN_TOP 0x4000		/* SPRITEパターン先頭アドレス */
#define SPRITE_TOP  (PATTERN_TOP >> 5)	/* パターン番号先頭 */
#define FONT_TOP    0x0400		/* HuC6270-BG フォント先頭アドレス */

struct SAT {				/* SAT 構造体 */
  unsigned short pos_y;			/* Ｙ座標 */
  unsigned short pos_x;			/* Ｘ座標 */
  unsigned short pattern_no;		/* パターン番号 */
  unsigned char  color;			/* スプライトカラー */
  unsigned char  spbg;			/* SP:1 /BG:0 優先順位 */
  unsigned char  cgx;			/* 0:横16dot 1:横32dot */
  unsigned char  x_bar;			/* 0:通常 1:横反転 */
  unsigned char  cgy;			/* 縦 0:16 1:32 2:48 3:64 dot */
  unsigned char  y_bar;			/* 0:通常 1:縦反転 */
};

extern unsigned short KINGBack[];	/* HuC6272 背景 */
extern unsigned short KINGColor[];	/* カラーパレット */
extern unsigned short SUPBack[];	/* HuC6270 背景 */
extern unsigned short SUPSprite[];	/* スプライトパターン */
void DeviceSet(void);
void SUPClear(char);
void SUPLine(char, char);
void SUPSatClear(void);
void SUPSatWrite(struct SAT *sat_entry, unsigned short dist_no);
void shoot(void);

/*------------------------------------------------------------------


  ------------------------------------------------------------------*/
char shot;				/* タマが撃たれたかどうか */
unsigned short tmpX;			/* タマのＸ座標 */
unsigned short tmpY = 0;		/* タマのＹ座標 */
struct SAT     tmp_att;			/* タマのＳＡＴ */
/*------------------------------------------------------------------


  ------------------------------------------------------------------*/
void
main(void)
{
  int i;
  char step;				/* 移動する速さ */
  unsigned char counter;		/* アニメーション用 */
  struct SCRL70 scrl70;			/* スクロール用構造体 */
  struct SAT    sprite_att;		/* 自機ＳＡＴ */
  struct SAT    fire_att;		/* 火焔ＳＡＴ */

  DeviceSet();				/* 初期設定 */
  /* sprite param. set */
  sprite_att.pos_x = 100;
  sprite_att.pos_y = 100;
  sprite_att.pattern_no = SPRITE_TOP;
  sprite_att.color = 0;
  sprite_att.spbg = 0;
  sprite_att.cgx = 0;
  sprite_att.x_bar = 0;
  sprite_att.cgy = 0;
  sprite_att.y_bar = 0;

  fire_att.pos_x = 100 - 16;
  fire_att.pos_y = 100;
  fire_att.pattern_no = SPRITE_TOP + 2;
  fire_att.color = 0;
  fire_att.spbg = 0;
  fire_att.cgx = 0;
  fire_att.x_bar = 0;
  fire_att.cgy = 0;
  fire_att.y_bar = 0;

  tmp_att.pos_y = 0;
  tmp_att.pattern_no = SPRITE_TOP + 6;
  tmp_att.color = 0;
  tmp_att.spbg = 0;
  tmp_att.cgx = 0;
  tmp_att.x_bar = 0;
  tmp_att.cgy = 0;
  tmp_att.y_bar = 0;

  /* sprite put */
  SUPSatWrite(&sprite_att, 0);		/* 自機ＳＡＴ書き込み */
  SUPSatWrite(&fire_att, 1);		/* 火焔ＳＡＴ書き込み */
  /* dummy */
  get_pad();
  shot = 0;				/* タマは撃たれてない */
  /* main routin */
  for (i = 0; i <= 512; i++){		/* ループ */
    get_pad();				/* パッド入力 */
    i = i & 0x1ff;			/* 永久ループにするため */
    KINGScroll(0, (i / 2) & 0xff, 0);	/* HuC6272 横スクロール */
    scrl70.bxr70 = i & 0xff;
    scrl70.byr70 = 0;
    set_70_scrl(&scrl70, DEV70A);	/* HuC6270 横スクロール */
    if (pad00.KD_TRG & KP_1 && shot == 0) { /* １ボタンでFire! */
      shot = 1;				/* タマうった */
      tmpX = sprite_att.pos_x + 16;	/* 自分の座標を教える */
      tmpY = sprite_att.pos_y;
    }
    /* ２ボタン押しっぱなしでダッシュ！ */
    if (pad00.KD_DAT & KP_2) step = 2; else step = 1;
    /* 上で、Ｙ座標を減らす 上限は 68 dot目 */
    if (pad00.KD_DAT & KP_up    && (sprite_att.pos_y > 68))
	sprite_att.pos_y -= step;
    /* 下で、Ｙ座標を増やす 下限は 264 dot目 */
    if (pad00.KD_DAT & KP_down  && (sprite_att.pos_y < 264))
	sprite_att.pos_y += step;
    /* 左で、Ｘ座標を減らす 左限は 34 dot目 */
    if (pad00.KD_DAT & KP_left  && (sprite_att.pos_x > 34))
	sprite_att.pos_x -= step;
    /* 右で、Ｘ座標を増やす 右限は 260 dot目 */
    if (pad00.KD_DAT & KP_right && (sprite_att.pos_x < 260))
	sprite_att.pos_x += step;
    /* 火焔位置調整 */
    fire_att.pos_y = sprite_att.pos_y;
    fire_att.pos_x = sprite_att.pos_x - 16;
    /* 火焔アニメーション */
    fire_att.pattern_no = SPRITE_TOP + 2 + ((counter & 0x04) >> 1);
    /* タマ撃たれているなら、撃つ処理へ */
    if (shot == 1) shoot();
    /* ＳＡＴ書き込み */
    SUPSatWrite(&sprite_att, 0);
    SUPSatWrite(&fire_att, 1);
    /* ６０分の１秒待つ */
    sat_trans_trg(SAT_TOP, DEV70A);	/* スプライト表示要求 */
    VSyncWait();
    /* カウンターを増やす */
    counter++;
  }
}

/*------------------------------------------------------------------
  撃つ！
  ------------------------------------------------------------------*/
void
shoot(void)
{
    /* 位置調整 */
    tmp_att.pos_x = tmpX;
    tmp_att.pos_y = tmpY;
    /* 前に進める */
    tmpX += 4;
    /* 画面外まで行ったらタマは撃ってないことにする */
    if(tmpX > 280){
        shot = 0;
        tmp_att.pos_y = 0;
    }
    /* ＳＡＴ書き込み */
    SUPSatWrite(&tmp_att, 2);
}
/*------------------------------------------------------------------
  初期化
  ------------------------------------------------------------------*/
void
DeviceSet(void)
{
  /* 初期化 */
  DevInit();
  RasterInit();
  init_70();
  /* 表示オフ */
  dispoff(bg0 | bg1 | bg2 | bg3 | bg | spr | rain);
  /* HuC6272 設定 */
  KINGScreen(2);		/* 内部ドット256色 + 外部ブロック256色 */
  KINGCylinder(0, 1);		/* 茶筒モード */
  KINGCls(0);			/* 内部ドット面クリア */
  KINGCls(2);			/* 外部ブロック面クリア */
  KINGTrans(0, KINGBack, 1);	/* 内部ドット面に背景転送 */
  fill_kram(0x20000, 0x0000, 0xefff); /* 外部ブロック面フォントクリア */
  /* HuC6261 カラーパレット設定 */
  write_pallet_datas(0, KINGColor, 256);
  /* HuC6261 スプライトカラーパレット設定 */
  write_pallet_datas(0x100, KINGColor, 256);
  /* HuC6270 設定 */
  /* ＢＧフォント転送（８１９２バイト） */
  mram_to_vram(FONT_TOP, SUPBack, 8192 / sizeof(short), DEV70A);
  /* スプライト転送 （８１９２バイト）*/
  SUPSatClear();		/* ＳＡＴクリア */
  mram_to_vram(PATTERN_TOP, SUPSprite, /* スプライトフォント転送 */
	       8192 / sizeof(short), DEV70A);
  set_70_mode(SPR_BG_ON, DEV70A); /* スプライト／ＢＧ表示オン */
  SUPClear(0x40);		/* ＢＧ面を0x40（空白フォント）で Fill */
  SUPLine(26, 0x41);		/* 画面作成 */
  SUPLine(27, 0x43);
  SUPLine(28, 0x43);
  SUPLine(29, 0x43);
  /* 割り込み設定 */
  /* パッド初期化 */
  init_get_pad();
  set_get_pad_mode(0, KC_IN, 1);
  set_get_pad_mode(1, KC_IN, 1);
  /* パッド入力ルーチンを割り込み駆動ルーチンに登録 */
  IrqSet(int_pad, XINT_KP);
  IrqOn(XINT_KP);                /* KPort 割り込みを有効に */
  IrqOn(XINT_72);                /* HuC6272 割り込みを有効に */
  irq_enable();                        /* 割り込みを許可 */
  /* 表示オン */
  dispon(bg0 | bg | spr);
}
/*------------------------------------------------------------------
  HuC6270 ＢＧ面に対し横１ラインにキャラクタを並べる
  ------------------------------------------------------------------*/
void
SUPLine(char y, char chnum)
{
  unsigned short supAddress;

  supAddress = SUP_XMAX * y;
  fill_vram(supAddress, (unsigned short)chnum, SUP_YMAX, DEV70A);
}
/*------------------------------------------------------------------
  HuC6270 ＢＧ面を指定キャラクタでクリアする
  （３２×３２モードのみ）
  ------------------------------------------------------------------*/
void
SUPClear(char chnum)
{
  fill_vram(0, (unsigned short)chnum, SUP_XMAX * SUP_YMAX, DEV70A);
}
/*------------------------------------------------------------------
  ＳＡＴ書き込み
  ------------------------------------------------------------------*/
void
SUPSatWrite(struct SAT *sat_entry, unsigned short dist_no)
{
  unsigned short satentry[4];
  unsigned short write_address;

  satentry[0] = sat_entry->pos_y & 0x3ff;
  satentry[1] = sat_entry->pos_x & 0x3ff;
  satentry[2] = sat_entry->pattern_no & 0x7ff;
  satentry[3] = sat_entry->color & 0x0f;
  satentry[3] |= (sat_entry->spbg & 1) << 7 || (sat_entry->cgx & 1) << 8;
  satentry[3] |= (sat_entry->x_bar & 1) << 11 || (sat_entry->cgy & 2) << 12;
  satentry[3] |= (sat_entry->y_bar & 1) << 15;
  write_address = SAT_TOP + SAT_SIZE * dist_no;
  mram_to_vram(write_address, satentry, SAT_SIZE, DEV70A);
}
/*------------------------------------------------------------------
  ＳＡＴクリア
  ------------------------------------------------------------------*/
void
SUPSatClear(void)
{
  fill_vram(SAT_TOP, 0x00, SAT_SIZE * 64, DEV70A);
}
